from typing import List, Optional, Dict, Any
from sqlalchemy.orm import Session
from sqlalchemy import and_, or_
import logging
import uuid
import json
from datetime import datetime

from app.models.database import Task
from app.models.schemas import TaskConfig, TaskInfo, TaskStatus, TaskListParams, PaginatedResponse
from app.services.crawl_service import MockCrawlService

logger = logging.getLogger(__name__)

class SimpleTaskService:
    """简化的任务服务 - 使用同步SQLAlchemy"""
    
    def __init__(self):
        self.crawl_service = MockCrawlService()
    
    def create_task(self, config: TaskConfig, db: Session) -> TaskInfo:
        """创建新任务"""
        try:
            # 生成任务ID
            task_id = str(uuid.uuid4())
            
            # 创建任务对象
            task = Task(
                id=task_id,
                name=config.name,
                description=config.description or "",
                urls=config.urls,
                config=self._config_to_dict(config),
                status="pending"
            )
            
            db.add(task)
            db.commit()
            db.refresh(task)
            
            logger.info(f"Task created: {task_id}")
            return self._task_to_info(task)
            
        except Exception as e:
            db.rollback()
            logger.error(f"Failed to create task: {e}")
            raise
    
    def get_task(self, task_id: str, db: Session) -> Optional[TaskInfo]:
        """获取任务详情"""
        try:
            task = db.query(Task).filter(Task.id == task_id).first()
            if task:
                return self._task_to_info(task)
            return None
        except Exception as e:
            logger.error(f"Failed to get task {task_id}: {e}")
            return None
    
    def list_tasks(self, params: TaskListParams, db: Session) -> PaginatedResponse:
        """获取任务列表"""
        try:
            query = db.query(Task)
            
            # 状态过滤
            if params.status:
                query = query.filter(Task.status == params.status.value)
            
            # 搜索过滤
            if params.search:
                query = query.filter(
                    or_(
                        Task.name.contains(params.search),
                        Task.description.contains(params.search)
                    )
                )
            
            # 计算总数
            total = query.count()
            
            # 分页
            offset = (params.page - 1) * params.size
            tasks = query.offset(offset).limit(params.size).all()
            
            # 转换为TaskInfo
            items = [self._task_to_info(task) for task in tasks]
            
            return PaginatedResponse(
                items=items,
                total=total,
                page=params.page,
                size=params.size,
                pages=(total + params.size - 1) // params.size
            )
            
        except Exception as e:
            logger.error(f"Failed to list tasks: {e}")
            raise
    
    def update_task(self, task_id: str, config: TaskConfig, db: Session) -> Optional[TaskInfo]:
        """更新任务"""
        try:
            task = db.query(Task).filter(Task.id == task_id).first()
            if not task:
                return None
            
            # 更新任务字段
            task.name = config.name
            task.description = config.description or ""
            task.urls = config.urls
            task.config = self._config_to_dict(config)
            task.updated_at = datetime.utcnow()
            
            db.commit()
            db.refresh(task)
            
            logger.info(f"Task updated: {task_id}")
            return self._task_to_info(task)
            
        except Exception as e:
            db.rollback()
            logger.error(f"Failed to update task {task_id}: {e}")
            raise
    
    def delete_task(self, task_id: str, db: Session) -> bool:
        """删除任务"""
        try:
            task = db.query(Task).filter(Task.id == task_id).first()
            if not task:
                return False
            
            db.delete(task)
            db.commit()
            
            logger.info(f"Task deleted: {task_id}")
            return True
            
        except Exception as e:
            db.rollback()
            logger.error(f"Failed to delete task {task_id}: {e}")
            raise
    
    def start_task(self, task_id: str, db: Session) -> bool:
        """启动任务"""
        try:
            task = db.query(Task).filter(Task.id == task_id).first()
            if not task:
                return False
            
            if task.status in ["running"]:
                logger.warning(f"Task {task_id} is already running")
                return False
            
            # 更新任务状态
            task.status = "running"
            task.started_at = datetime.utcnow()
            task.updated_at = datetime.utcnow()
            
            # 初始化日志
            if not task.logs:
                task.logs = []
            
            # 添加启动日志
            log_entry = {
                "timestamp": datetime.utcnow().isoformat(),
                "level": "INFO",
                "message": f"Task {task_id} started"
            }
            logs = task.logs or []
            logs.append(log_entry)
            task.logs = logs
            
            db.commit()
            
            # 这里可以启动实际的爬取任务
            # self.crawl_service.start_crawl(task_id, task.config)
            
            logger.info(f"Task started: {task_id}")
            return True
            
        except Exception as e:
            db.rollback()
            logger.error(f"Failed to start task {task_id}: {e}")
            raise
    
    def stop_task(self, task_id: str, db: Session) -> bool:
        """停止任务"""
        try:
            task = db.query(Task).filter(Task.id == task_id).first()
            if not task:
                return False
            
            if task.status not in ["running"]:
                logger.warning(f"Task {task_id} is not running")
                return False
            
            # 更新任务状态
            task.status = "stopped"
            task.completed_at = datetime.utcnow()
            task.updated_at = datetime.utcnow()
            
            # 添加停止日志
            log_entry = {
                "timestamp": datetime.utcnow().isoformat(),
                "level": "INFO",
                "message": f"Task {task_id} stopped"
            }
            logs = task.logs or []
            logs.append(log_entry)
            task.logs = logs
            
            db.commit()
            
            logger.info(f"Task stopped: {task_id}")
            return True
            
        except Exception as e:
            db.rollback()
            logger.error(f"Failed to stop task {task_id}: {e}")
            raise
    
    def get_task_status(self, task_id: str, db: Session) -> Optional[Dict[str, Any]]:
        """获取任务状态"""
        try:
            task = db.query(Task).filter(Task.id == task_id).first()
            if not task:
                return None
            
            return {
                "task_id": task_id,
                "status": task.status,
                "progress": task.progress,
                "pages_crawled": task.pages_crawled,
                "pages_total": task.pages_total,
                "success_rate": task.success_rate,
                "errors_count": task.errors_count,
                "started_at": task.started_at.isoformat() if task.started_at else None,
                "updated_at": task.updated_at.isoformat() if task.updated_at else None
            }
            
        except Exception as e:
            logger.error(f"Failed to get task status {task_id}: {e}")
            return None
    
    def _task_to_info(self, task: Task) -> TaskInfo:
        """将Task对象转换为TaskInfo"""
        return TaskInfo(
            id=task.id,
            name=task.name,
            description=task.description or "",
            urls=task.urls or [],
            status=TaskStatus(task.status),
            progress=task.progress,
            pages_crawled=task.pages_crawled,
            pages_total=task.pages_total,
            success_rate=task.success_rate,
            errors_count=task.errors_count,
            config=task.config or {},
            created_at=task.created_at,
            updated_at=task.updated_at,
            started_at=task.started_at,
            completed_at=task.completed_at
        )
    
    def _config_to_dict(self, config: TaskConfig) -> Dict[str, Any]:
        """将TaskConfig转换为字典"""
        if hasattr(config, 'dict'):
            return config.dict()
        elif hasattr(config, '__dict__'):
            return config.__dict__
        else:
            return {}
